package iohelper

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"hash/crc32"
	"io"
	"reflect"
	"runtime/debug"
	"sync"
	"unsafe"
)

const cMaxArrSize = 0xFFFFFFFFF // 64G

type PByteArray (*[cMaxArrSize]byte)
type PUint16Array (*[cMaxArrSize]uint16)
type PUint32Array (*[cMaxArrSize]uint32)
type PUint64Array (*[cMaxArrSize]uint64)
type PStrArray (*[cMaxArrSize]string)
type HashIdType = int32 // =, 用别名，方便兼容
type typeIdHash map[HashIdType]*typeInfo
type typeHash map[reflect.Type]*typeInfo

type fieldInfo struct {
	offset     uintptr
	size       uint32 // 大小，0 为动态大小需要计算，切片，字符串等
	kind       reflect.Kind
	arrLen     uint32       // 数组长度，只有数组才有
	elemKind   reflect.Kind // 数组和切片的元素类型
	elemType   reflect.Type // 创建切片的时候要用到
	elemSize   uint32       // 单个元素的大小，只有切片会用到
	tp         reflect.Type // 当前字段的类型，创建切片要用到
	structInfo *typeInfo    // 如果是结构体就指向结构信息，结果是结构体切片或数组时，这里也指向结构体的类型信息
}

type typeInfo struct {
	id        HashIdType
	fields    []fieldInfo // 所有字段
	tp        reflect.Type
	dynFields []fieldInfo // 动态大小的字段，如：切片、字符串等
	fixedSize uint32      // 固定字段的大小，计算长度只用计算动态字段的长度
	crc32     uint32      // 可以识别出字段是否兼容
}

type Serializer struct {
	typeHashTable typeHash
	idHashTable   typeIdHash
	isLikeCRecord bool         // 是否跟C++ Record 兼容的方式
	mu            sync.RWMutex // 读写锁
	autoSeedId    HashIdType   // 当注册自带类型时，自动用负数
}

// 方便线程和不同的模式使用 isLikeCStruct 主要是跟 c++、Delphi 类通讯
func NewSerializer(isLikeCStruct bool, hashTblSize int) *Serializer {
	ret := &Serializer{idHashTable: make(typeIdHash, hashTblSize), typeHashTable: make(typeHash, hashTblSize), isLikeCRecord: isLikeCStruct}
	return ret
}

// 是否为固定大小的类型
func isFixedSizeKind(kind reflect.Kind) bool {
	ret := false
	if (kind >= reflect.Bool) && (kind <= reflect.Complex128) {
		ret = true
	}
	return ret
}

type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}

// 获取切片的长度
func getSliceLength(ptr unsafe.Pointer) int {
	return (*(*SliceHeader)(ptr)).Len
}

type emptyInterface struct {
	typ *struct{}
	ptr unsafe.Pointer
}

func GetValueDataPtr(v *reflect.Value) unsafe.Pointer {
	return (*(*emptyInterface)(unsafe.Pointer(v))).ptr
}

func (s *Serializer) addType(id HashIdType, tpInfo *typeInfo) bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	if id > 0 {
		s.idHashTable[id] = tpInfo
	}
	s.typeHashTable[tpInfo.tp] = tpInfo
	return true
}

func (s *Serializer) idIsExists(id HashIdType) bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	_, ok := s.idHashTable[id]
	return ok
}

func (s *Serializer) regType(id HashIdType, tp reflect.Type) (*typeInfo, error) {

	defer func() {
		if err := recover(); err != nil {
			fmt.Println("regType: error ", err, string(debug.Stack()))
		}
	}()

	if tp.Kind() == reflect.Array {
		return nil, fmt.Errorf("不要注册数组类型")
	}

	if id == 0 {
		s.mu.Lock()
		s.autoSeedId--
		id = s.autoSeedId
		s.mu.Unlock()
	}

	tpInfo := new(typeInfo)
	tpInfo.tp = tp
	tpInfo.id = id

	fldCnt := tp.NumField()
	buff := bytes.NewBuffer(nil)
	binary.Write(buff, binary.LittleEndian, uint16(fldCnt))

	// log.Println("type.kind = ", tp.Kind(), tp.Name(), fldCnt)

	for i := 0; i < fldCnt; i++ {
		fld := tp.Field(i)
		fldInfo := fieldInfo{} // 清空
		fldInfo.offset = fld.Offset
		fldInfo.kind = fld.Type.Kind()
		fldInfo.tp = fld.Type

		binary.Write(buff, binary.LittleEndian, uint8(fldInfo.kind))

		// log.Println("regType: ", i, tp, fld.Type.Kind(), fld.Type, uint8(fldInfo.kind))

		if isFixedSizeKind(fldInfo.kind) {
			fldInfo.size = uint32(fld.Type.Size()) // 可以直接 copy
		} else {
			switch fldInfo.kind {
			case reflect.Array, reflect.Slice:
				fldInfo.elemType = fld.Type.Elem()
				fldInfo.elemKind = fldInfo.elemType.Kind()

				if fldInfo.elemKind == reflect.Struct {
					sTpInfo, _ := s.tryGetTypeInfo(fldInfo.elemType)
					if sTpInfo == nil { // 没找到，直接注册
						sTpInfo, _ = s.regType(0, fldInfo.elemType)
					}
					fldInfo.structInfo = sTpInfo
				}

				binary.Write(buff, binary.LittleEndian, uint32(fldInfo.elemKind)) // 写入元素类型
				if isFixedSizeKind(fldInfo.elemKind) {
					fldInfo.elemSize = uint32(fldInfo.elemType.Size())
				}

				if fldInfo.kind == reflect.Array {
					fldInfo.arrLen = uint32(fld.Type.Len())
					binary.Write(buff, binary.LittleEndian, fldInfo.arrLen) // 数组还要写入长度
					if isFixedSizeKind(fldInfo.elemKind) {
						fldInfo.size = uint32(fld.Type.Size())
					}
				}

			case reflect.String:
				fldInfo.size = 0

			case reflect.Struct:
				sTpInfo, _ := s.tryGetTypeInfo(fld.Type)
				if sTpInfo == nil { // 没找到，直接注册
					sTpInfo, _ = s.regType(0, fld.Type)
				}
				fldInfo.structInfo = sTpInfo

				binary.Write(buff, binary.LittleEndian, sTpInfo.crc32) // 结构直接写入crc，子结构变了，本结构也会跟着变，类似区块链

				//log.Println("注册结构体: ", *sTpInfo)

			default:
				return nil, fmt.Errorf("不支持的字段类型，注册失败 %v, %v", fldInfo.kind, fld)
			}
		}

		if fldInfo.size == 0 {
			tpInfo.dynFields = append(tpInfo.dynFields, fldInfo) // 请加动态字段
		} else {
			tpInfo.fixedSize += fldInfo.size // 累加固定大小
		}

		// log.Println("regType: append ", tp, i, fldInfo.tp, fldInfo.kind)
		tpInfo.fields = append(tpInfo.fields, fldInfo)
	}
	// log.Println("regType: crcbits = ", buff.Bytes())
	tpInfo.crc32 = crc32.ChecksumIEEE(buff.Bytes())
	// log.Println("regType: tpinfo = ", tp, ", crc32 = ", tpInfo.crc32)
	s.addType(id, tpInfo)
	return tpInfo, nil
}

func (s *Serializer) RegisterType(id HashIdType, obj any) error {
	if s.idIsExists(id) {
		panic(fmt.Sprintf("Serializer.RegisterType id 重复: %v", id))
	}

	tp := reflect.TypeOf(obj)
	if tp.Kind() == reflect.Ptr {
		tp = tp.Elem()
	}

	_, err := s.regType(id, tp)

	return err
}

func (s *Serializer) writeSlice(w *WriteHelper, slicePtr unsafe.Pointer, fld *fieldInfo) (n int, err error) {
	sliceLen := getSliceLength(slicePtr)
	n, err = w.WriteDynLen(uint64(sliceLen))
	if err != nil {
		return
	}
	var l int
	if sliceLen > 0 { // 可以copy的类型
		switch fld.elemKind {
		case reflect.Int8, reflect.Uint8:
			slice := *(*[]byte)(unsafe.Pointer(slicePtr))
			l, err = WriteSlice(w, slice)
			if err != nil {
				return
			}
			n += l

		case reflect.Int16, reflect.Uint16:
			slice := *(*[]uint16)(unsafe.Pointer(slicePtr))
			l, err = WriteSlice(w, slice)
			if err != nil {
				return
			}
			n += l

		case reflect.Int32, reflect.Uint32:
			slice := *(*[]uint32)(unsafe.Pointer(slicePtr))
			l, err = WriteSlice(w, slice)
			if err != nil {
				return
			}
			n += l

		case reflect.Int64, reflect.Uint64:
			slice := *(*[]uint64)(unsafe.Pointer(slicePtr))
			l, err = WriteSlice(w, slice)
			if err != nil {
				return
			}
			n += l

		case reflect.String:
			slice := *(*[]string)(unsafe.Pointer(slicePtr))
			l, err = WriteSlice(w, slice)
			if err != nil {
				return
			}
			n += l

		case reflect.Struct:
			if fld.structInfo != nil {
				// fmt.Println("field type = ", fld.tp, "elelment type = ", fld.elemType)
				sliceFld := reflect.NewAt(fld.tp, slicePtr)
				sliceFld = reflect.Indirect(sliceFld)
				for i := 0; i < sliceFld.Len(); i++ {
					v := sliceFld.Index(i)
					if l, err = s.writeValue(v, w); err != nil {
						return n, fmt.Errorf("writeSlice: writeValue error %v", err)
					}
					n += l
				}
			} else {
				return n, fmt.Errorf("writeSlice: 没有注册的切片类型 %v", fld.elemType)
			}

		default:
			return n, fmt.Errorf("writeSlice: 不支持的类型 %v", fld.elemKind)
		}
	}
	return
}

func (s *Serializer) writeArray(w *WriteHelper, arrayPtr unsafe.Pointer, fld *fieldInfo) (n int, err error) {
	var l int
	if fld.arrLen > 0 { // 可以copy的类型
		switch fld.elemKind {
		case reflect.Int8, reflect.Uint8:
			arr := (PByteArray)(unsafe.Pointer(arrayPtr))
			l, err = WriteSlice(w, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int16, reflect.Uint16:
			arr := (PUint16Array)(unsafe.Pointer(arrayPtr))
			l, err = WriteSlice(w, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int32, reflect.Uint32:
			arr := (PUint32Array)(unsafe.Pointer(arrayPtr))
			l, err = WriteSlice(w, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int64, reflect.Uint64:
			arr := (PUint64Array)(unsafe.Pointer(arrayPtr))
			l, err = WriteSlice(w, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.String:
			arr := (PStrArray)(unsafe.Pointer(arrayPtr))
			l, err = WriteSlice(w, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Struct:
			if fld.structInfo != nil {
				fldValue := reflect.NewAt(fld.tp, arrayPtr)
				fldValue = reflect.Indirect(fldValue)
				for i := 0; i < int(fld.arrLen); i++ {
					v := fldValue.Index(i)
					if l, err = s.writeValue(v, w); err != nil {
						return n, fmt.Errorf("writeArray writeValue error: %v", err)
					}
					n += l
				}
			} else {
				return n, fmt.Errorf("writeArray: 结构类型未注册 %v %v", fld.elemKind, fld.elemType)
			}

		default:
			return n, fmt.Errorf("writeArray: 不支持的类型 %v %v", fld.elemKind, fld.elemType)
		}
	}
	return
}

func (s *Serializer) readSlice(r *ReadHelper, slicePtr unsafe.Pointer, fld *fieldInfo) (n int, err error) {
	var sliceLen uint64
	sliceLen, err = r.ReadDynLen()
	if err != nil {
		return
	}
	n += GetLengthDataLen(int(sliceLen))
	var l int
	if sliceLen > 0 { // 可以copy的类型
		switch fld.elemKind {
		case reflect.Int8, reflect.Uint8:
			slice := make([]byte, sliceLen)
			l, err = ReadSlice(r, slice)
			if err != nil {
				return
			}
			n += l
			*(*[]byte)(unsafe.Pointer(slicePtr)) = slice

		case reflect.Int16, reflect.Uint16:
			slice := make([]uint16, sliceLen)
			l, err = ReadSlice(r, slice)
			if err != nil {
				return
			}
			n += l
			*(*[]uint16)(unsafe.Pointer(slicePtr)) = slice

		case reflect.Int32, reflect.Uint32:
			slice := make([]uint32, sliceLen)
			l, err = ReadSlice(r, slice)
			if err != nil {
				return
			}
			n += l
			*(*[]uint32)(unsafe.Pointer(slicePtr)) = slice

		case reflect.Int64, reflect.Uint64:
			slice := make([]uint64, sliceLen)
			l, err = ReadSlice(r, slice)
			if err != nil {
				return
			}
			n += l
			*(*[]uint64)(unsafe.Pointer(slicePtr)) = slice

		case reflect.String:
			slice := make([]string, sliceLen)
			l, err = ReadSlice(r, slice)
			if err != nil {
				return
			}
			n += l
			*(*[]string)(unsafe.Pointer(slicePtr)) = slice

		case reflect.Struct:
			if fld.structInfo != nil {
				fldValue := reflect.NewAt(fld.tp, slicePtr)
				fldValue = reflect.Indirect(fldValue)
				sliceFld := reflect.MakeSlice(fld.tp, int(sliceLen), int(sliceLen))
				for i := 0; i < sliceFld.Len(); i++ {
					v := sliceFld.Index(i)

					if l, err = s.readValue(v, r); err != nil {
						return n, fmt.Errorf("writeSlice: writeValue error %v", err)
					}
					n += l
				}
				fldValue.Set(sliceFld)
			} else {
				return n, fmt.Errorf("writeSlice: 没有注册的切片类型 %v", fld.elemType)
			}

		default:
			return n, fmt.Errorf("readSlice: 不支持的类型 %v %v", fld.elemKind, fld.elemType)
		}
	}
	return
}

func (s *Serializer) readArray(r *ReadHelper, arrPtr unsafe.Pointer, fld *fieldInfo) (n int, err error) {
	var l int
	if fld.arrLen > 0 { // 可以copy的类型
		switch fld.elemKind {
		case reflect.Int8, reflect.Uint8:
			arr := (PByteArray)(unsafe.Pointer(arrPtr))
			l, err = ReadSlice(r, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int16, reflect.Uint16:
			arr := (PUint16Array)(unsafe.Pointer(arrPtr))
			l, err = ReadSlice(r, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int32, reflect.Uint32:
			arr := (PUint32Array)(unsafe.Pointer(arrPtr))
			l, err = ReadSlice(r, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Int64, reflect.Uint64:
			arr := (PUint64Array)(unsafe.Pointer(arrPtr))
			l, err = ReadSlice(r, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.String:
			arr := (PStrArray)(unsafe.Pointer(arrPtr))
			l, err = ReadSlice(r, (*arr)[:fld.arrLen])
			if err != nil {
				return
			}
			n += l

		case reflect.Struct:
			if fld.structInfo != nil {
				fldValue := reflect.NewAt(fld.tp, arrPtr)
				fldValue = reflect.Indirect(fldValue)
				for i := 0; i < int(fld.arrLen); i++ {
					v := fldValue.Index(i)
					if l, err = s.readValue(v, r); err != nil {
						return n, fmt.Errorf("readArray readValue error: %v", err)
					}
					n += l
				}
			} else {
				return n, fmt.Errorf("readArray: 结构类型未注册 %v %v", fld.elemKind, fld.elemType)
			}

		default:
			return n, fmt.Errorf("readArray: 不支持的类型 %v %v", fld.elemKind, fld.elemType)
		}
	}
	return
}

func getStringWriteLen(str string) int {
	l := len(str)
	return AddLengthDataLen(l)
}

// 计算切片的写入长度
func getSliceWriteLen(ptr uintptr, fld *fieldInfo) int {
	len := getSliceLength(unsafe.Pointer(ptr))
	writeLen := GetLengthDataLen(len)
	if fld.elemSize > 0 {
		writeLen += len * int(fld.elemSize)
	} else {
		switch fld.elemKind {
		case reflect.String:
			ps := (*[]string)(unsafe.Pointer(ptr))
			for i := 0; i < len; i++ {
				writeLen += getStringWriteLen((*ps)[i])
			}
		default:
			// log.Println("不支持的字段切片类型计算长度 ", fld.elemType)
			return 0
		}
	}
	return writeLen
}

func getArrayWriteLen(ptr uintptr, fld *fieldInfo) int {
	writeLen := 0
	switch fld.elemKind {
	case reflect.String:
		psArr := (PStrArray)(unsafe.Pointer(ptr))
		for i := 0; i < int(fld.arrLen); i++ {
			writeLen += getStringWriteLen((*psArr)[i])
		}
	default:
		// log.Println("不支持的数组类型计算长度，类型=", fld.elemType)
		return 0
	}
	return writeLen
}

// 计算动态字段的长度
func (pInfo *typeInfo) calcDataSize(valuePtr uintptr) int {
	// log.Println("calcDataSize: ", len(pInfo.fields), *pInfo)
	fldLen := len(pInfo.dynFields)
	result := int(pInfo.fixedSize)
	for i := 0; i < fldLen; i++ {
		fld := &pInfo.dynFields[i]
		addr := valuePtr + fld.offset
		// log.Println("calcDataSize: ", pInfo.tp, i, fld.kind)
		switch fld.kind {
		case reflect.String:
			result += getStringWriteLen(*(*string)(unsafe.Pointer(addr)))

		case reflect.Slice:
			result += getSliceWriteLen(addr, fld)

		case reflect.Array:

			result += getArrayWriteLen(addr, fld)

		case reflect.Struct: // 结构递归运算
			// log.Println("calcDataSize, offset = ", fld.offset)
			result += fld.structInfo.calcDataSize(addr)

		default:
			// log.Println("未处理的类型 ", fld.kind, pInfo.tp.Name())
			return 0
		}
	}

	// log.Println("calcDataSize: result = ", result)
	return result
}

func (s *Serializer) tryGetTypeInfo(tp reflect.Type) (atpInfo *typeInfo, ret bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	tpInfo, ok := s.typeHashTable[tp]
	return tpInfo, ok
}

func (s *Serializer) getTypeInfo(tp reflect.Type) (atpInfo *typeInfo, isOk bool) {

	tpInfo, ok := s.tryGetTypeInfo(tp)
	if !ok {
		var err error
		tpInfo, err = s.regType(0, tp) // 找不到就直接注册一个
		if err != nil {
			return nil, false
		}
	}
	return tpInfo, tpInfo != nil
}

func (s *Serializer) encodeStruct(w *WriteHelper, valuePtr unsafe.Pointer, tpInfo *typeInfo) (n int, err error) {
	var l int
	for i := 0; i < len(tpInfo.fields); i++ {
		fld := &(tpInfo.fields[i])

		fldAddr := unsafe.Add(valuePtr, fld.offset)
		pFld := unsafe.Pointer(fldAddr)

		switch fld.kind { // 下面这种写法能提升10%的速度
		case reflect.Int8, reflect.Uint8:
			l, err = w.WriteByte(*(*uint8)(pFld))
			if err != nil {
				return
			}
			n += l
		case reflect.Int16, reflect.Uint16:
			l, err = w.WriteUint16(*(*uint16)(pFld))
			if err != nil {
				return
			}
			n += l
		case reflect.Int32, reflect.Uint32:
			l, err = w.WriteUint32(*(*uint32)(pFld))
			if err != nil {
				return
			}
			n += l
		case reflect.Int64, reflect.Uint64:
			l, err = w.WriteUint64(*(*uint64)(pFld))
			if err != nil {
				return
			}
			n += l

		case reflect.String:
			str := *(*string)(pFld)
			l, err = w.WriteString(str)
			if err != nil {
				return
			}
			n += l

		case reflect.Slice:
			l, err = s.writeSlice(w, fldAddr, fld)
			if err != nil {
				return
			}
			n += l

		case reflect.Array:
			l, err = s.writeArray(w, fldAddr, fld)
			if err != nil {
				return
			}
			n += l

		case reflect.Struct:
			l, err = s.encodeStruct(w, fldAddr, fld.structInfo)
			if err != nil {
				return
			}
			n += l

		default:
			return n, fmt.Errorf("不支持的类型 %v", fld.kind)
		}
	}
	return
}

// 根据注册ID新建结构，方便外面使用
func (s *Serializer) NewStruct(id HashIdType) interface{} {
	info, isOk := s.idHashTable[id]
	if isOk {
		v := reflect.New(info.tp)
		return v.Interface()
	}
	return nil
}

func (s *Serializer) writeValue(value reflect.Value, w *WriteHelper) (n int, err error) {

	value = reflect.Indirect(value)

	tpInfo, ok := s.getTypeInfo(value.Type())
	if !ok {
		return n, fmt.Errorf("找不到类型信息，应该没有注册")
	}

	valuePtr := GetValueDataPtr(&value)

	// if !s.isLikeCRecord {
	// allSize := tpInfo.calcDataSize(valuePtr)
	// n := GetLengthDataLen(allSize)

	// bits = make([]byte, cCRC32Size+n+allSize) // 开始要写CRC+len

	// *(*uint32)(unsafe.Pointer(&bits[idx])) = tpInfo.crc32
	// idx += cCRC32Size

	// WiriteLength(bits[idx:], allSize) // 写入总长度

	// idx += n
	// }

	n, err = s.encodeStruct(w, valuePtr, tpInfo)

	return
}

func (s *Serializer) EncodeTo(ptr any, w io.Writer) (n int, err error) {

	value := reflect.ValueOf(ptr)
	srcType := value.Type()

	if value.Type().Kind() != reflect.Ptr {
		return 0, fmt.Errorf("编码只能传指针， 为了提高效率 %v", value.Type())
	}

	value = reflect.Indirect(value)

	if value.Type().Kind() == reflect.Ptr {
		return 0, fmt.Errorf("不要使用二级指针。。。太费事了 %v", srcType)
	}

	wt := NewWriteHelper(w, nil)

	var l int
	kind := value.Type().Kind()
	if kind == reflect.Slice || kind == reflect.Array {
		arrLen := value.Len()
		if kind == reflect.Slice {
			if l, err = wt.WriteDynLen(uint64(arrLen)); err != nil {
				return
			}
			n += l
		}

		for i := 0; i < arrLen; i++ {
			ev := value.Index(i)
			if l, err = s.writeValue(ev, wt); err != nil {
				return n, fmt.Errorf("EncodeTo slice error, idx = %d, err = %s", i, err)
			}
			n += l
		}
	} else {
		return s.writeValue(value, wt)
	}
	return
}

// 这里传指针，加快访问速度，不用注册，没类型会自动注册，如果是网络协议中就要先注册
func (s *Serializer) Encode(ptr any) (result []byte, err error) {
	var buff bytes.Buffer
	buff.Grow(128)
	if _, err := s.EncodeTo(ptr, &buff); err != nil {
		return nil, fmt.Errorf("Encode error: %s", err)
	}
	return buff.Bytes(), err
}

func (s *Serializer) decodeStruct(r *ReadHelper, valuePtr unsafe.Pointer, tpInfo *typeInfo) (n int, err error) {
	var l int
	for i := 0; i < len(tpInfo.fields); i++ {
		fld := &(tpInfo.fields[i])
		fldAddr := unsafe.Add(valuePtr, fld.offset)
		pFld := unsafe.Pointer(fldAddr)
		switch fld.kind {
		case reflect.Int8, reflect.Uint8:
			*(*byte)(pFld), err = r.ReadByte()
			n += 1
		case reflect.Int16, reflect.Uint16:
			*(*int16)(pFld), err = r.ReadInt16()
			n += 2
		case reflect.Int32, reflect.Uint32:
			*(*int32)(pFld), err = r.ReadInt32()
			n += 4
		case reflect.Int64, reflect.Uint64:
			*(*int64)(pFld), err = r.ReadInt64()
			n += 8
		case reflect.String:
			var str string
			str, err = r.ReadString()
			if err != nil {
				return
			}
			l = len(str)
			*(*string)(pFld) = str
			n += l + GetLengthDataLen(l)

		case reflect.Slice:
			l, err = s.readSlice(r, fldAddr, fld)
			if err != nil {
				return
			}
			n += l
		case reflect.Array:
			l, err = s.readArray(r, fldAddr, fld)
			if err != nil {
				return
			}
			n += l

		case reflect.Struct:
			l, err = s.decodeStruct(r, fldAddr, fld.structInfo)
			if err != nil {
				return
			}
			n += l

		default:
			return n, fmt.Errorf("decodeStruct 不支持的类型: %v", fld.kind)
		}
	}
	return
}

func (s *Serializer) readValue(value reflect.Value, r *ReadHelper) (n int, err error) {

	value = reflect.Indirect(value)

	tpInfo, ok := s.getTypeInfo(value.Type())
	if !ok {
		return n, fmt.Errorf("找不到类型信息，应该没有注册")
	}

	valuePtr := GetValueDataPtr(&value)

	// if !s.isLikeCRecord {
	// allSize := tpInfo.calcDataSize(valuePtr)
	// n := GetLengthDataLen(allSize)

	// bits = make([]byte, cCRC32Size+n+allSize) // 开始要写CRC+len

	// *(*uint32)(unsafe.Pointer(&bits[idx])) = tpInfo.crc32
	// idx += cCRC32Size

	// WiriteLength(bits[idx:], allSize) // 写入总长度

	// idx += n
	// }

	n, err = s.decodeStruct(r, valuePtr, tpInfo)

	return
}

func (s *Serializer) DecodeFrom(r io.Reader, ptr any) (n int, err error) {
	value := reflect.ValueOf(ptr)
	srcType := value.Type()
	if value.Type().Kind() != reflect.Ptr {
		return 0, fmt.Errorf("编码只能传指针， 为了提高效率 %v", value.Type())
	}

	value = reflect.Indirect(value)

	if value.Type().Kind() == reflect.Ptr {
		return 0, fmt.Errorf("不要使用二级指针。。。太费事了 %v", srcType)
	}

	rd := NewReadHelper(r, nil)

	var l int
	kind := value.Type().Kind()
	if kind == reflect.Slice || kind == reflect.Array {
		if kind == reflect.Slice {
			sliceLen, e := rd.ReadDynLen()
			if e != nil {
				return n, e
			}
			n += GetLengthDataLen(int(sliceLen))
			newSlice := reflect.MakeSlice(value.Type(), int(sliceLen), int(sliceLen))
			value.Set(newSlice)
		}

		for i := 0; i < value.Len(); i++ {
			ev := value.Index(i)
			if l, err = s.readValue(ev, rd); err != nil {
				return n, fmt.Errorf("DecodeTo slice error, idx = %d, err = %s", i, err)
			}
			n += l
		}
	} else {
		return s.readValue(value, rd)
	}
	return
}

func (s *Serializer) Decode(bits []byte, ptr any) (n int, err error) {
	buff := bytes.NewBuffer(bits)
	return s.DecodeFrom(buff, ptr)
}

func (s *Serializer) DecodeStruct(id HashIdType, bits []byte) (obj interface{}, err error) {
	obj = s.NewStruct(id)
	if obj != nil {
		_, err = s.Decode(bits, obj)
	} else {
		err = fmt.Errorf("DecodeStruct: 找到到注册的类型 %v", id)
	}
	return
}
